package com.chuangjiangx.member.coupon.ddd.domain.repository;

import com.chuangjiangx.commons.BeanUtils;
import com.chuangjiangx.commons.exception.BaseException;
import com.chuangjiangx.dddbase.Repository;
import com.chuangjiangx.dddbase.domain.shared.Timestamp;
import com.chuangjiangx.member.coupon.ddd.domain.model.*;
import com.chuangjiangx.member.coupon.dao.mapper.InMbrCouponMapper;
import com.chuangjiangx.member.coupon.dao.model.InMbrCoupon;
import com.chuangjiangx.member.coupon.dao.model.InMbrCouponExample;

import com.chuangjiangx.member.basic.ddd.domain.model.MerchantId;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class MbrCouponRepository implements Repository<MbrCoupon, MbrCouponId> {

    private final InMbrCouponMapper inMbrCouponMapper;

    @Autowired
    public MbrCouponRepository(InMbrCouponMapper inMbrCouponMapper) {
        this.inMbrCouponMapper = inMbrCouponMapper;
    }

    @Override
    public MbrCoupon fromId(MbrCouponId id) {
        Objects.requireNonNull(id);
        InMbrCoupon inMbrCoupon = inMbrCouponMapper.selectByPrimaryKey(id.getId());
        if (inMbrCoupon == null) {
            return null;
        }
        return convertToEntity(inMbrCoupon);
    }

    @Override
    public void update(MbrCoupon entity) {
        Objects.requireNonNull(entity);
        InMbrCoupon inMbrCoupon = convertToIn(entity);
        inMbrCouponMapper.updateByPrimaryKeySelective(inMbrCoupon);
    }

    /**
     * 根据卡券编号查询
     * @return 卡券编号
     */
    public MbrCoupon fromCouponNumber(String couponNumber) {
        Objects.requireNonNull(couponNumber);
        InMbrCouponExample example = new InMbrCouponExample();
        example.createCriteria().andCouponNumberEqualTo(couponNumber);
        List<InMbrCoupon> inMbrCoupons = inMbrCouponMapper.selectByExample(example);
        if (inMbrCoupons == null || inMbrCoupons.size() == 0) {
            return null;
        }
        if (inMbrCoupons.size() > 1) {
            throw new BaseException("-1","卡券数据异常");
        }
        return convertToEntity(inMbrCoupons.get(0));
    }

    /**
     * 根据微信卡券id查询
     * @return 卡券编号
     */
    public MbrCoupon fromWxCardId(String wxCardId) {
        Objects.requireNonNull(wxCardId);
        InMbrCouponExample example = new InMbrCouponExample();
        example.createCriteria().andWxCardIdEqualTo(wxCardId);
        List<InMbrCoupon> inMbrCoupons = inMbrCouponMapper.selectByExample(example);
        if (inMbrCoupons == null || inMbrCoupons.size() == 0) {
            return null;
        }
        if (inMbrCoupons.size() > 1) {
            throw new BaseException("-1","卡券数据异常");
        }
        return convertToEntity(inMbrCoupons.get(0));
    }

    /**
     * 修改库存
     */
    public void inventoryUpdate(MbrCoupon oldCoupon, Long newInventory, Long newAvailInventory) {
        Objects.requireNonNull(oldCoupon);
        Objects.requireNonNull(newInventory);
        Objects.requireNonNull(newAvailInventory);
        InMbrCouponExample example = new InMbrCouponExample();
        example.createCriteria()
                .andIdEqualTo(oldCoupon.getId().getId())
                .andAvailInventoryEqualTo(oldCoupon.getAvailInventory());

        InMbrCoupon inMbrCoupon = convertToIn(oldCoupon);
        inMbrCoupon.setTotalInventory(newInventory);
        inMbrCoupon.setAvailInventory(newAvailInventory);
        inMbrCoupon.setUpdateTime(new Date());
        inMbrCouponMapper.updateByExampleSelective(inMbrCoupon,example);
    }

    @Override
    public void save(MbrCoupon entity) {
        InMbrCoupon in = convertToIn(entity);
        in.setDeleted(0);
        Date endTime = DateUtils.setHours(in.getActTimeEnd(), 23);
        endTime = DateUtils.setMinutes(endTime,59);
        endTime = DateUtils.setSeconds(endTime,59);
        in.setActTimeEnd(endTime);
        in.setActTimeStart(DateUtils.truncate(in.getActTimeStart(),Calendar.DATE));
        inMbrCouponMapper.insert(in);
        entity.setId(new MbrCouponId(in.getId()));
    }

    /**
     * 删除卡券
     * @param mbrCouponId 卡券id
     */
    public void delete(MbrCouponId mbrCouponId) {
        Objects.requireNonNull(mbrCouponId);
        MbrCoupon oldMbrCoupon = fromId(mbrCouponId);
        InMbrCoupon inMbrCoupon = convertToIn(oldMbrCoupon);
        inMbrCoupon.setDeleted(1);
        inMbrCouponMapper.updateByPrimaryKeySelective(inMbrCoupon);
    }



    private MbrCoupon convertToEntity(InMbrCoupon in) {
        Objects.requireNonNull(in);
        MbrCoupon mbrCoupon = new MbrCoupon(in.getCouponNumber(), new MerchantId(in.getMerchantId()),
                in.getName(),in.getAmount(), MbrCouponType.getType(in.getType()),
                in.getLogo(), ValidType.getType(in.getValidType()),in.getValidTimeStart(),in.getValidTimeEnd(),
                in.getClaimedTime(),in.getTotalInventory(),in.getAvailInventory(),
                in.getRemark(),in.getMiniExpendLimit(),in.getClaimUpperLimit(),
                InvalidRemindType.getType(in.getRemindType()),in.getUseTimeWeek(),
                in.getUseTimeDay(), MbrCouponSourceType.getSourceType(in.getCouponSourceType()),
                in.getActTimeStart(),in.getActTimeEnd(),in.getWxColor(),in.getSyncType(),in.getWxCenterSubTitle(),
                WxAuditStatus.getWxAuditStatus(in.getWxAuditStatus()),in.getWxCardId(),in.getWxRefuseReason());
        mbrCoupon.setId(new MbrCouponId(in.getId()));
        mbrCoupon.setTimestamp(new Timestamp(in.getCreateTime(),in.getUpdateTime()));
        return mbrCoupon;
    }

    private InMbrCoupon convertToIn(MbrCoupon mbrCoupon) {
        Objects.requireNonNull(mbrCoupon);
        InMbrCoupon in = new InMbrCoupon();
        BeanUtils.convertBean(mbrCoupon,in);
        Optional<MbrCoupon> coupon = Optional.of(mbrCoupon);
        in.setId(coupon.map(MbrCoupon::getId).map(MbrCouponId::getId).orElse(null));
        in.setCreateTime(mbrCoupon.getTimestamp().getCreateTime());
        in.setUpdateTime(mbrCoupon.getTimestamp().getUpdateTime());
        in.setMerchantId(mbrCoupon.getMerchantId().getId());
        in.setType(coupon.map(MbrCoupon::getType).map(type -> type.code).orElse(null));
        in.setValidType(coupon.map(MbrCoupon::getValidType).map(type -> type.code).orElse(null));
        in.setRemindType(coupon.map(MbrCoupon::getRemindType).map(type -> type.code).orElse(null));
        in.setCouponSourceType(coupon.map(MbrCoupon::getCouponSourceType).map(type -> type.code).orElse(null));
        in.setWxAuditStatus(coupon.map(MbrCoupon::getWxAuditStatus).map(type -> type.code).orElse(null));
        return in;
    }


}
